package com.mediatek.settings.wifi;

import java.util.Enumeration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.io.IOException;

import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;

import android.security.Credentials;
import android.security.keystore.KeyProperties;
import android.security.KeyStore2;
import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;

import android.app.AlertDialog;
import android.content.Context;
import android.net.NetworkInfo.DetailedState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiConfiguration.GroupCipher;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.PairwiseCipher;
import android.net.wifi.WifiConfiguration.Protocol;
import android.net.wifi.WifiManager;
import android.os.SystemProperties;

import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;

import com.android.settings.R;
import com.android.mtksettingslib.wifi.AccessPoint;
import com.android.settings.utils.ManagedServiceSettings.Config;
import com.android.settings.wifi.WifiConfigController2;
import com.android.settings.wifi.WifiConfigUiBase2;
import com.mediatek.settings.FeatureOption;
import com.mediatek.settings.UtilsExt;
import com.mediatek.settings.ext.IWifiExt;
import android.util.Log;
import com.android.wifitrackerlib.WifiEntry;
import com.android.wifitrackerlib.WifiEntry.ConnectedInfo;

public class WifiConfigControllerExt {
    private static final String TAG = "WifiConfigControllerExt";
    private final WifiManager mWifiManager;  // Add for WAPI @{

    // Add for WAPI @{
    private Spinner mWapiCert;
    private static final String WLAN_PROP_KEY = "persist.vendor.sys.wlan";
    private static final String WIFI = "wifi";
    private static final String WAPI = "wapi";
    private static final String WIFI_WAPI = "wifi-wapi";
    private static final String DEFAULT_WLAN_PROP = WIFI_WAPI;
    private final List<String> mWapiAliases = new ArrayList<>();
    // Updated WAPI_PSK and WAPI_CERT security value as two more
    // security types are added by Google
    // These securty used from Wifienrty so it is commented here
    // public static final int SECURITY_WAPI_PSK = 7;
    // public static final int SECURITY_WAPI_CERT = 8;
    // @}

    // Add for plug in
    private IWifiExt mExt;
    private Context mContext;
    private View mView;
    private WifiConfigUiBase2 mConfigUi;
    private WifiConfigController2 mController;

    public WifiConfigControllerExt(WifiConfigController2 controller, WifiConfigUiBase2 configUi,
            View view) {
        mController = controller;
        Log.d(TAG,"WifiConfigControllerExt constr called ");
        mConfigUi = configUi;
        mContext = mConfigUi.getContext();
        mView = view;
        mExt = UtilsExt.getWifiExt(mContext);
        /// Init Wi-Fi manager
        mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
    }

    public void addViews(WifiConfigUiBase2 configUi, String security) {
        Log.d(TAG,"addViews called ");
        ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);
        // add security information
        View row = configUi.getLayoutInflater().inflate(R.layout.wifi_dialog_row, group, false);
        ((TextView) row.findViewById(R.id.name)).setText(configUi.getContext().getString(
                R.string.wifi_security));
         // mExt.setSecurityText((TextView) row.findViewById(R.id.name));
        ((TextView) row.findViewById(R.id.value)).setText(security);
        group.addView(row);
    }

    public void setConfig(WifiConfiguration config, int accessPointSecurity, TextView passwordView,
            Spinner eapMethodSpinner) {
        // get priority of configuration TODO 2019 Check below code
        Log.d(TAG,"setConfig called with accessPointSecurity"+accessPointSecurity);
        //config.wapiCertSelMode = 0;
        switch (accessPointSecurity) {
        // Add WAPI_PSK & WAPI_CERT @{
        case WifiEntry.SECURITY_WAPI_PSK:
            config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WAPI_PSK);
            if (passwordView.length() != 0) {
                String password = passwordView.getText().toString();
                config.preSharedKey = '"' + password + '"';
            }
            break;

        case WifiEntry.SECURITY_WAPI_CERT:
            config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_WAPI_CERT);
            config.enterpriseConfig =  new WifiEnterpriseConfig();
            config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.WAPI_CERT);
            String aliases = new String();
            if (mWapiCert.getSelectedItemPosition() != 0) {
                aliases = mWapiCert.getSelectedItem().toString();
            } else {
                aliases = String.join(";", mWapiAliases.subList(1, mWapiAliases.size()));
            }
            config.enterpriseConfig.setWapiCertSuite(aliases);
            Log.d(TAG,"config.wapiCertSel  "+config.enterpriseConfig.getWapiCertSuite());
            break;
        // @}
        default:
            break;
        }
    }

    private static String addQuote(int s) {
        return "\"" + s + "\"";
    }
    /// M: for china mobile wlan feature start @{
    public void setEapmethodSpinnerAdapter() {
        // set array for eap method spinner. CMCC will show only eap and sim
        Context context = mConfigUi.getContext();
        String[] eapString = context.getResources().getStringArray(R.array.wifi_eap_method);
        ArrayList<String> eapList = new ArrayList<String>(Arrays.asList(eapString));
        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(context,
                android.R.layout.simple_spinner_item, eapList);
        if (mController.getWifiEntry() != null) {
           mExt.setEapMethodArray(adapter, getAccessPointSsid(), getAccessPointSecurity());
        }
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        // Add for triggering onItemSelected
        Spinner eapMethodSpinner = (Spinner) mView.findViewById(R.id.method);
        eapMethodSpinner.setAdapter(adapter);
    }

    public void setEapMethodFields(boolean edit) {
        Spinner eapMethodSpinner = (Spinner) mView.findViewById(R.id.method);
        int eapMethod = eapMethodSpinner.getSelectedItemPosition();
        // for CMCC-AUTO eap Method config information
        if (mController.getWifiEntry() != null) {
            eapMethod = mExt.getEapMethodbySpinnerPos(eapMethod, getAccessPointSsid(),
                   getAccessPointSecurity());
        }
        Log.d(TAG, "showSecurityFields modify method = " + eapMethod);
        // for CMCC ignore some config information
        /*mExt.hideWifiConfigInfo(new IWifiExt.Builder().setAccessPoint(mController.getWifiEntry())
                .setEdit(edit).setViews(mView), mConfigUi.getContext());*/
    }
    /// M }@

    /**
     * add for EAP & WAPI
     */
    public boolean showSecurityFields(int accessPointSecurity, boolean edit) {
        Log.d(TAG, "showSecurityFields, accessPointSecurity = " + accessPointSecurity);
        Log.d(TAG, "showSecurityFields, edit = " + edit);

        // show WAPI_CERT field
        if (accessPointSecurity == WifiEntry.SECURITY_WAPI_CERT) {
            mView.findViewById(R.id.security_fields).setVisibility(View.GONE);
            mView.findViewById(R.id.wapi_cert_fields).setVisibility(View.VISIBLE);
            mWapiCert = (Spinner) mView.findViewById(R.id.wapi_cert);
            mWapiCert.setOnItemSelectedListener(mController);
            loadCertificates(mWapiCert);

            if (mController.getWifiEntry() != null && mController.getWifiEntry().isSaved()) {
                WifiConfiguration config = getAccessPointConfig();
                setCertificate(mWapiCert, "WAPI");
            }
            return true;
        } else {
            mView.findViewById(R.id.wapi_cert_fields).setVisibility(View.GONE);
        }

        // for CMCC ignore some config information
        /*mExt.hideWifiConfigInfo(new IWifiExt.Builder().setAccessPoint(mController.getWifiEntry())
                .setEdit(edit).setViews(mView), mConfigUi.getContext());*/
        return false;
    }

    private void setCertificate(Spinner spinner, String cert) {
        Log.d(TAG, "setSelection, cert = " + cert);
        if (cert != null) {
            @SuppressWarnings("unchecked")
            ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
            for (int i = adapter.getCount() - 1; i >= 0; --i) {
                if (cert.equals(adapter.getItem(i))) {
                    spinner.setSelection(i);
                    break;
                }
            }
        }
    }

    public boolean enableSubmitIfAppropriate(TextView passwordView, int accessPointSecurity,
            boolean pwInvalid) {
        boolean passwordInvalid = pwInvalid;
        if (passwordView != null
                && ((accessPointSecurity == WifiEntry.SECURITY_WEP && !isWepKeyValid(passwordView
                        .getText().toString())) ||
                        ((accessPointSecurity == WifiEntry.SECURITY_PSK && passwordView
                        .length() < 8) || (accessPointSecurity == WifiEntry.SECURITY_WAPI_PSK
                        && (passwordView.length() < 8
                        || 64 < passwordView.length()))))) {
            passwordInvalid = true;
        }
        return passwordInvalid;
    }

    public int getEapMethod(int eapMethod) {
        Log.d(TAG, "getEapMethod, eapMethod = " + eapMethod);
        int result = eapMethod;
        if (mController.getWifiEntry() != null) {
            result = mExt.getEapMethodbySpinnerPos(eapMethod, getAccessPointSsid(),
                    getAccessPointSecurity());
        }
        Log.d(TAG, "getEapMethod, result = " + result);
        return result;
    }

    public void setEapMethodSelection(Spinner eapMethodSpinner, int eapMethod) {
        int eapMethodPos = eapMethod;
        if (mController.getWifiEntry() != null) {
            eapMethodPos = mExt.getPosByEapMethod(eapMethod, getAccessPointSsid(),
                    getAccessPointSecurity());
        }
        eapMethodSpinner.setSelection(eapMethodPos);
        Log.d(TAG, "[skyfyx]showSecurityFields modify pos = " + eapMethodPos);
        Log.d(TAG, "[skyfyx]showSecurityFields modify method = " + eapMethod);

    }

    /**
     * 1.Add some more security spinners to support WAPI 2.Switch spinner
     * according to WIFI & WAPI config
     */
    public void addWifiConfigView(boolean edit) {
        // set security text
        //TextView securityText = (TextView) mView.findViewById(R.id.security_text);
        //mExt.setSecurityText(securityText);
        Log.d(TAG,"addWifiConfigView called ");
        if (mController.getWifiEntry() == null) {
            // set array for wifi security
            Spinner mSecuritySpinner = ((Spinner) mView.findViewById(R.id.security));
            ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(mContext,
                            android.R.layout.simple_spinner_item, android.R.id.text1);
            spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            mSecuritySpinner.setAdapter(spinnerAdapter);
            int idx = 0;
           Log.d(TAG,"addWifiConfigView WITH GETcOUNT "+spinnerAdapter.getCount());
            if (FeatureOption.MTK_WAPI_SUPPORT) {
                String type = SystemProperties.get(WLAN_PROP_KEY, DEFAULT_WLAN_PROP);
                Log.d(TAG, "addWifiConfigView, type = " + type);
                if (type.equals(WIFI_WAPI)) {
                    idx = addWifiItems(spinnerAdapter, idx);
                    spinnerAdapter.add(mContext.getString(R.string.wapi_psk));
                    mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_WAPI_PSK;
                    spinnerAdapter.add(mContext.getString(R.string.wifi_security_wapi_certificate));
                    mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_WAPI_CERT;

                } else if (type.equals(WIFI)) {
                    idx = addWifiItems(spinnerAdapter, idx); // WIFI only, AOSP
                } else if (type.equals(WAPI)) {
                    // WAPI only
                    spinnerAdapter.add(mContext.getString(R.string.wapi_psk));
                    mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_WAPI_PSK;
                    spinnerAdapter.add(mContext.getString(R.string.wifi_security_wapi_certificate));
                    mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_WAPI_CERT;
                }
            } else {
                idx = addWifiItems(spinnerAdapter, idx); // WIFI only, AOSP
            }

            spinnerAdapter.notifyDataSetChanged();
        } else {
            WifiConfiguration config = getAccessPointConfig();
            Log.d(TAG, "addWifiConfigView, config = " + config);
            // Whether to show access point priority select spinner.
            if (mController.getWifiEntry().isSaved() && config != null) {
                Log.d(TAG, "priority=" + config.priority);
            }
        }

        // for CMCC ignore some config information
        /*mExt.hideWifiConfigInfo(new IWifiExt.Builder().setAccessPoint(mController.getWifiEntry())
                .setEdit(edit).setViews(mView), mConfigUi.getContext());*/
    }

    private int addWifiItems(ArrayAdapter<String> spinnerAdapter, int idx) {
        // Populate the Wi-Fi security spinner with the various supported key management types
        Log.d(TAG," addWifiItems called with spinner value "+spinnerAdapter+"and    idx "+idx);
        Log.d(TAG, Log.getStackTraceString(new Exception()));
        spinnerAdapter.add(mContext.getString(R.string.wifi_security_none));
        mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_NONE;
        if (mWifiManager.isEnhancedOpenSupported()) {
            spinnerAdapter.add(mContext.getString(R.string.wifi_security_owe));
            mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_OWE;
        }
                   spinnerAdapter.add(mContext.getString(R.string.wifi_security_wep));
                   mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_WEP;
                   spinnerAdapter.add(mContext.getString(R.string.wifi_security_wpa_wpa2));
                   mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_PSK;
                   if (mWifiManager.isWpa3SaeSupported()) {
                       spinnerAdapter.add(mContext.getString(R.string.wifi_security_sae));
                       mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_SAE;
                   }
                   spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap));
                   mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_EAP;
                   if (mWifiManager.isWpa3SuiteBSupported()) {
                       spinnerAdapter.add(mContext.getString(R.string.wifi_security_eap_suiteb));
                       mController.mSecurityInPosition[idx++] = WifiEntry.SECURITY_EAP_SUITE_B;
                   }
                   Log.d(TAG," addWifiItems called with spinner value 2 "+spinnerAdapter+"and    idx "+idx);
        return idx;
    }

    private boolean isWepKeyValid(String password) {
        if (password == null || password.length() == 0) {
            return false;
        }
        int keyLength = password.length();
        /// M: ALPS03001760, confirmed by wap_supplicant, we don't support WEP-152 AP
        if (((keyLength == 10 || keyLength == 26) && password
                .matches("[0-9A-Fa-f]*"))
                || (keyLength == 5 || keyLength == 13)) {
            return true;
        }
        return false;
    }

    private void loadCertificates(Spinner spinner) {
        final Context context = mConfigUi.getContext();
        String autoSelectCert = context.getString(R.string.wapi_auto_sel_cert);
        mWapiAliases.clear();
        mWapiAliases.add(autoSelectCert);
        try {
            final KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
            KeyStore.LoadStoreParameter loadParam =
                    new AndroidKeyStoreLoadStoreParameter(KeyProperties.NAMESPACE_WIFI);
            keyStore.load(loadParam);

            final Enumeration<String> aliases = keyStore.aliases();
            while (aliases.hasMoreElements()) {
                final String alias = aliases.nextElement();
                if (alias.startsWith("WAPI_USRCERT_"))
                    mWapiAliases.add(alias.replace("WAPI_USRCERT_", ""));
            }
        } catch (KeyStoreException |
                 CertificateException |
                 IOException |
                 NoSuchAlgorithmException e) {
            Log.e(TAG, "Error while loading entries from keystore.", e);
        }

        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(context,
                android.R.layout.simple_spinner_item,
                mWapiAliases.toArray(new String[0]));
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinner.setAdapter(adapter);
    }

    /**
     * get the security to its corresponding security spinner position
     */
    public int getSecurity(int accessPointSecurity) {
        Log.d(TAG, "getSecurity, accessPointSecurity = " + accessPointSecurity);
        // Only WPAI supported
        Log.d(TAG, Log.getStackTraceString(new Exception()));
        if (FeatureOption.MTK_WAPI_SUPPORT) {
            String type = SystemProperties.get(WLAN_PROP_KEY, DEFAULT_WLAN_PROP);
            if (type.equals(WAPI) && accessPointSecurity > 0) {
                accessPointSecurity += WifiEntry.SECURITY_WAPI_PSK - WifiEntry.SECURITY_WEP;
            }
        }
        Log.d(TAG, "getSecurity, accessPointSecurity = " + accessPointSecurity);
        return accessPointSecurity;
    }

    private WifiConfiguration getAccessPointConfig() {
        if (mController.getWifiEntry() != null) {
            return mController.getWifiEntry().getWifiConfiguration();
        }
        return null;
    }

    private String getAccessPointSsid() {
        if (mController.getWifiEntry() != null) {
            return mController.getWifiEntry().getTitle();
        }
        return null;
    }

    private int getAccessPointSecurity() {
        if (mController.getWifiEntry() != null) {
            return mController.getWifiEntry().getSecurity();
        }
        return 0;
    }

    private DetailedState getAccessPointState() {
       /*if (mController.getWifiEntry() != null) {
            return (mController.getWifiEntry().getNetworkInfo() != null ? mController
                    .getWifiEntry().getNetworkInfo().getDetailedState() : null);
        }*/
        return null;
    }
}
